本篇文章同步發表於 個人部落格 Jim's Blog
在網頁的開發中,上傳檔案是一個非常常見的需求,本章節會介紹在開發 Blazor 時,該怎麼來實現檔案上傳的功能,Server 和 WebAssembly 雖然細節上有些差異但大致上是相通的
建立一個新的元件,名稱為 FileUpload
@using System.Net.Http.Headers
@inject HttpClient Http
@page "/FileUpload"
<h3>檔案上傳</h3>
<InputFile OnChange="@OnInputFileChange" />
@code {
private bool shouldRender;
protected override bool ShouldRender() => shouldRender;
private async Task OnInputFileChange(InputFileChangeEventArgs e)
{
using var content = new MultipartFormDataContent();
foreach (var file in e.GetMultipleFiles())
{
var fileContent = new StreamContent(file.OpenReadStream(1024 * 1000));
fileContent.Headers.ContentType = new MediaTypeHeaderValue(file.ContentType);
content.Add(fileContent,"\"files\"",file.Name);
}
await Http.PostAsync("api/File", content);
shouldRender = true;
}
}
其中的 1024 * 100 是我要調整上傳檔案的大小的限制,預設為 500 KB
為了方便講解,沒有對檔案做必要的安全性處理,正式使用時請依照安全性原則處理檔案上傳
相關的資料可以查看官方文件 安全性考量
這邊建立了一個 type = file
的input
,並且在檔案變動時,發出Request將檔案串流到至伺服器端
完成 razor
元件的部分後,我們來處理 API Controller 的內容,建立一個 API 控制器名稱為 FileController
,並撰寫內容
[Route("api/[controller]")]
[ApiController]
public class FileController : ControllerBase
{
private readonly IWebHostEnvironment _env;
public FileController(IWebHostEnvironment env)
{
_env = env;
}
[HttpPost]
public async Task<IActionResult> PostFile([FromForm] IEnumerable<IFormFile> files)
{
var filesProcessed = 0;
foreach (var file in files)
{
var path = Path.Combine(_env.ContentRootPath,
_env.EnvironmentName, "image",
file.FileName);
await using FileStream fs = new(path, FileMode.Create);
await file.CopyToAsync(fs);
filesProcessed++;
}
return Ok();
}
}
在 Blazor Server 上的檔案上傳大同小異,只是要在 Program.cs
註冊HttpClient
builder.Services.AddHttpClient();
並且對剛剛 WebAssembly 的 Componet 做修改
@inject IHttpClientFactory ClientFactory
@using System.Net.Http.Headers
@page "/FileUpload"
<h3>檔案上傳</h3>
<InputFile OnChange="@OnInputFileChange" />
@code {
private bool shouldRender;
protected override bool ShouldRender() => shouldRender;
private async Task OnInputFileChange(InputFileChangeEventArgs e)
{
using var content = new MultipartFormDataContent();
foreach (var file in e.GetMultipleFiles())
{
var fileContent = new StreamContent(file.OpenReadStream(1024 * 1000));
fileContent.Headers.ContentType = new MediaTypeHeaderValue(file.ContentType);
content.Add(fileContent, "\"files\"", file.Name);
}
var client = ClientFactory.CreateClient();
await client.PostAsync("https://localhost:7197/api/File", content);
shouldRender = true;
}
}
有發現不一樣的地方嗎?@inject HttpClient Http
變成 @inject IHttpClientFactory ClientFactory
而API的部分是相同的所以可以直接參照上方的 API Controller
這邊透過簡單的方式去示範檔案上傳的做法,在真實環境中務必注意安全性,以免對資料造成損失,下一章會介紹兩種 Blazor 專案要怎麼呼叫 WebAPI